/*
 *   Copyright (C) 2009  Jens Kieselbach
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You may obtain a copy of the License at http://www.gnu.org/licenses/gpl.html
 */
package de.kieselbach.grootional.component

import de.kieselbach.swing.*
import de.kieselbach.swing.border.*

import com.jgoodies.looks.*
import com.jgoodies.looks.plastic.*
import groovy.swing.*
import javax.swing.*

import java.awt.BorderLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.Font
import java.awt.GridBagLayout
import java.awt.GridBagConstraints

class CardPane extends JPanel {

    final def borderColor
	final def activeBorder
	final def inactiveBorder
	
    final def parent
    final def uiResources
    final def resourceBundle
    final def editable

    def contentPanel

    def cards = [] as List
    def visibleCardIndex

    def visibleInternalCard
    def lastInternalCard

    def count = 0

    CardPane(def par, def uires) {

        this(par, uires, true, 5, 5, 5, 5)
    }

	CardPane(def par, def uires, def edit) {

		this(par, uires, edit, 5, 5, 5, 5)
	}
	
    CardPane(def par, def uires, def edit, def bt, def bl, def bb, def br) {

        super(new BorderLayout(0, 0))

        parent = par
        uiResources = uires
        resourceBundle = uiResources.resourceBundles['gui']
        editable = edit

        contentPanel = new JPanel(new GridBagLayout())
        contentPanel.border = BorderFactory.createEmptyBorder(bt, bl, bb, br)
        add(contentPanel)

        borderColor = UIUtilities.lineBorderColor
		activeBorder = CustomLineBorder.create(borderColor, '478962', 3, 5, 3, 5)
		inactiveBorder = CustomLineBorder.create(borderColor, '47896321', 3, 5, 3, 5)
    }

    void addCard(def card) {
        
        addCard(card, false)
    }

    void addCard(def card, def expanded) {

        if(card == null) {
            return
        }

        if(!expanded) {
            expanded = count <= 0
        }

        if(expanded && visibleInternalCard != null) {
            visibleInternalCard.box.visible = false
			visibleInternalCard.button.border = inactiveBorder
        }

        def index = count * 2

        cards.each() {p->
            if(p == card) {
                throw new IllegalArgumentException('the panel was already added!')
            }
        }

        def title = 'undefined'
        try {
            title = card.title
        }
        catch(Exception exc) {
            exc.printStackTrace()
        }

        def sb = new ExtendedSwingBuilder()
        sb.panel(contentPanel) {

            def button = sb.processableButton(title, icon: card.icon, requestFocusEnabled: false,
                focusPainted: false, horizontalTextPosition: SwingConstants.RIGHT, horizontalAlignment: SwingConstants.LEFT, font: font.deriveFont(Font.BOLD),
                constraints: gbc(gridx: 0, gridy: index, gridwidth: 1, gridheight: 1, weightx: 1.0, weighty: 0.0, ipady: 4, fill: GridBagConstraints.HORIZONTAL, insets: [count > 0 ? 5 : 0, 0, 0, 0]))

            if(card.processable) {
                button.setProcessingImage(uiResources.images['process-working'], 4, 8)
                card.processableButton = button

                if(card.processing) {
                    button.start()
                }
            }

            def bar = null
            def box = sb.panel(visible: expanded,
                constraints: gbc(gridx: 0, gridy: index + 1, gridwidth: 1, gridheight: 1, weightx: 1.0, weighty: 1.0, ipady: 2, fill: GridBagConstraints.BOTH, insets: [0, 0, 0, 0])) {

                sb.borderLayout()

                sb.panel(constraints: BorderLayout.CENTER) {
                    sb.borderLayout()

                    sb.panel(border: CustomLineBorder.create(borderColor, '46', 1, 2, 1, 2), constraints: BorderLayout.NORTH) {
                        sb.borderLayout()

                        bar = sb.box(constraints: BorderLayout.CENTER)
                    }

                    widget(card)
                }
            }

            def internalcard = new InternalCard(card, button, box, cards.size())
            cards << internalcard.card
            if(expanded) {
                visibleInternalCard = internalcard
                visibleCardIndex = internalcard.index
            }
			
			button.border = expanded ? activeBorder : inactiveBorder
            button.actionPerformed = {event ->
                if (!box.isVisible()) {
                    expand(internalcard)
                }
            }

            def maxh = 0
            def separators = [] as List

            card.toolBarItems.each {elem ->

                if(elem instanceof AbstractButton) {
                    elem.verticalAlignment = PaneBuilder.verticalButtonAligment
                }
                else if(elem instanceof CardSeparator) {
                    separators << elem
                }

                bar.add(elem)

                def h = elem.preferredSize.@height
                if(h > maxh) {
                    maxh = h
                }
            }

            if(editable) {
                if(card.addToolBarGlue) {
                    bar.add(Box.createHorizontalGlue())
                }

                def edit = new FlatButton(uiResources.images['title16'] as Icon)
                edit.verticalAlignment = PaneBuilder.verticalButtonAligment
                edit.toolTipText = resourceBundle.getString('card.rename')
                bar.add(edit)
                edit.actionPerformed = {
                    editTitle(internalcard)
                }

                def up = new FlatButton(uiResources.images['up16'] as Icon)
                up.verticalAlignment = PaneBuilder.verticalButtonAligment
                internalcard.upButton = up
                up.toolTipText = resourceBundle.getString('card.moveup')
                up.enabled = lastInternalCard != null
                bar.add(up)
                up.actionPerformed = {
                    moveCard(internalcard, true)
                }

                def down = new FlatButton(uiResources.images['down16'] as Icon)
                down.verticalAlignment = PaneBuilder.verticalButtonAligment
                internalcard.downButton = down
                down.toolTipText = resourceBundle.getString('card.movedown')
                down.enabled = false
                bar.add(down)
                down.actionPerformed = {
                    moveCard(internalcard, false)
                }

                def sep = new CardSeparator()
                separators << sep
                bar.add(sep)

                def close = new FlatButton(uiResources.images['close16'] as Icon)
                close.verticalAlignment = PaneBuilder.verticalButtonAligment
                close.toolTipText = resourceBundle.getString('card.close')
                bar.add(close)
                close.actionPerformed = {
                    closeCard(internalcard)
                }

                card.closeButton = close
                card.closeIcon = uiResources.images['close16']
                card.closeModifiedIcon = uiResources.images['closemodified16']

                if(card.processable) {
                    if(card.processing) {
                        card.closeButton.enabled = false
                        card.closeButtonState = true
                    }
                }

                def h = close.preferredSize.@height
                if(h > maxh) {
                    maxh = h
                }

                def size = [7, maxh] as Dimension
                separators.each() {sepelem ->
                    sepelem.minimumSize = sepelem.maximumSize = sepelem.preferredSize = size
                }

                if(lastInternalCard != null) {
                    lastInternalCard.downButton.enabled = true
                }
            }

            lastInternalCard = internalcard
        }

        count++

        contentPanel.validate()
        contentPanel.repaint()
    }

    // --------------------------------------------------------------------------------------------------    

    void moveCard(def internalcard, def up) {

        def oldcards = cards
        def oi = oldcards.indexOf(internalcard.card)
        if(oi >= 0) {

            def oldcard = oldcards.remove(oi)
            if(up) {
                oldcards.add(oi - 1, oldcard)
            }
            else {
                oldcards.add(oi + 1, oldcard)
            }

            cards = [] as List

            contentPanel.removeAll()
            visibleInternalCard = null
            visibleCardIndex = null
            lastInternalCard = null
            count = 0

            oldcards.each() {card ->
                addCard(card, card == oldcard)
            }

            contentPanel.validate()
            contentPanel.repaint()
        }
    }

    void closeCard(def internalcard) {

        def panebuilder = new PaneBuilder()
        if(panebuilder.question(resourceBundle.getString('card.close'), message: resourceBundle.getString('card.closeconfirmation'), owner: parent, options: ['yes', 'no'], default: 'yes') == 'yes') {

            internalcard.card.dispose()
            
            def oldcards = cards
            oldcards.remove(internalcard.card)
            cards = [] as List

            contentPanel.removeAll()
            visibleInternalCard = null
            visibleCardIndex = null
            lastInternalCard = null
            count = 0

            oldcards.each() {card ->
                addCard(card)
            }

            contentPanel.validate()
            contentPanel.repaint()
        }
    }

    void editTitle(def internalcard) {

        def field = new JTextField(internalcard.card.title as String)
        field.opaque = false
        field.font = internalcard.button.font
        field.preferredSize = internalcard.button.size
        field.border = BorderFactory.createEmptyBorder(0, 5, 0, 0)

        def popup = new JPopupMenu()
		popup.border = CustomLineBorder.create(borderColor, '478962')
        popup.layout = new BorderLayout(0, 0)

        popup.add(field, BorderLayout.CENTER)
        popup.preferredSize = internalcard.button.size

        field.actionPerformed = {
            def  t = field.text.trim()
            if(t.length() > 0) {
                internalcard.card.title = t
                internalcard.button.text = t
                popup.visible = false
            }
        }

        popup.show(internalcard.button, 0, 0)

        SwingUtilities.invokeLater {
            field.requestFocus()
            field.selectAll()
        }
    }

    void expand(def internalcard) {

        internalcard.box.preferredSize = null
        internalcard.box.visible = true
        internalcard.box.invalidate()

        visibleInternalCard.box.visible = false
		visibleInternalCard.button.border = inactiveBorder
        visibleInternalCard.box.invalidate()

        validate()
        repaint()

        visibleInternalCard = internalcard
		visibleInternalCard.button.border = activeBorder
        visibleCardIndex = internalcard.index
    }
}
